<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\Common\Constants\StatusConstants;
use App\CustHub\Mapper\ChRoleSchemeMapper;
use App\CustHub\Model\ChRobot;
use App\CustHub\Model\ChRoom;
use App\CustHub\Model\ChRoomGroup;
use Hyperf\DbConnection\Db;
use Mine\Abstracts\AbstractService;
use Mine\Annotation\Transaction;
use Mine\Exception\NormalStatusException;
use Mine\MineModel;
use function Hyperf\Collection\collect;
use function Hyperf\Collection\data_get;

class RoleSchemeService extends AbstractService
{
    public $mapper;

    public function __construct(ChRoleSchemeMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    /**
     * 获取角色方案列表
     * @param array $params
     * @return array
     */
    public function getSchemeList(array $params): array
    {
        $pageSize = data_get($params,'page_size',MineModel::PAGE_SIZE);
        $createUid = data_get($params,'create_uid');

        $p = $this->mapper->model::query()
            ->select(['id','name','role_num','room_num','group_num'])
            ->where('main_uid',$params['main_uid'])
            ->when($createUid,function ($query) use ($createUid){
                $query->where('uid',$createUid);
            })
            ->orderByRaw('sort desc,created_at desc')
            ->paginate((int)$pageSize);

        return $this->mapper->setPaginate($p);
    }

    /**
     * 新增方案
     * @param array $data
     * @return mixed
     */
    #[Transaction]
    public function save(array $data): mixed
    {
        $id = $this->mapper->save($data);
        return $this->mapper->update($id,['sort' => $id]);
    }

    public function getInfo(array $params)
    {
        $info = $this->mapper->findById($params['id']);
        is_null($info->crew_list) && $info->crew_list = [];
        is_null($info->role_list) && $info->role_list = [];
        $info = $info->toArray();
        if(!empty($info['crew_list'])){
            $roomIdList = [];
            $roomGroupIdList = [];
            $robotIds = [];
            foreach ($info['crew_list'] as $item){
                if(!empty($item['roomList'])){
                    foreach ($item['roomList'] as $roomItem){
                        if($roomItem['type'] == 'room'){
                            $roomIdList[] = $roomItem['value'];
                        }else{
                            $roomGroupIdList[] = $roomItem['value'];
                        }
                    }
                }

                if(!empty($item['roleList'])){
                    foreach ($item['roleList'] as $roleItem){
                        if(!empty($roleItem['robotIds'])){
                            //目前只支持一个机器人
                            $robotIds[] = array_shift($roleItem['robotIds']);
                        }
                    }
                }
            }

            $roomMap = [];
            if(!empty($roomIdList)){
                $roomIdList = array_unique($roomIdList);
                $roomList = ChRoom::query()
                    ->select(['id','room_name','room_avatar_url'])
                    ->whereIn('id',$roomIdList)
                    ->get();

                $roomMap = collect($roomList)->keyBy('id')->toArray();
            }

            $roomGroupMap = [];
            if(!empty($roomGroupIdList)){
                $roomGroupIdList = array_unique($roomGroupIdList);
                $roomGroupList = ChRoomGroup::query()
                    ->select(['id','name'])
                    ->whereIn('id',$roomGroupIdList)
                    ->get();

                $roomGroupMap = collect($roomGroupList)->keyBy('id')->toArray();
            }

            $robotMap = [];
            if(!empty($robotIds)){
                $robotIds = array_unique($robotIds);
                $robotList = ChRobot::query()
                    ->select(['id','nickname','avatar'])
                    ->whereIn('id',$robotIds)
                    ->get();

                $robotMap = collect($robotList)->keyBy('id')->toArray();
            }

            foreach ($info['crew_list'] as $k=>$item){
                if(!empty($item['roomList'])){
                    foreach ($item['roomList'] as $rk=>$roomItem){
                        if($roomItem['type'] == 'room'){
                            $info['crew_list'][$k]['roomList'][$rk]['roomInfo'] = $roomMap[$roomItem['value']] ?? '';
                        }else{
                            $info['crew_list'][$k]['roomList'][$rk]['roomGroupInfo'] = $roomGroupMap[$roomItem['value']] ?? '';
                        }
                    }
                }

                if(!empty($item['roleList'])){
                    foreach ($item['roleList'] as $rk=>$roleItem){
                        if(!empty($roleItem['robotIds'])){
                            //目前只支持一个机器人
                            $robotId = array_shift($roleItem['robotIds']);
                            $info['crew_list'][$k]['roleList'][$rk]['robotInfo'] = $robotMap[$robotId] ?? '';
                        }
                    }
                }
            }
        }

        return $info;
    }

    public function updateScheme(array $data): bool
    {
        $info = $this->mapper->findById($data['id']);
        if(empty($info)){
            throw new NormalStatusException("操作失败");
        }

        if(!empty($data['crew_list'])){
            $crew_list = json_decode($data['crew_list'],true);
            $data['crew_list'] = $crew_list;
            $roomNum = 0;
            $groupNum = 0;
            foreach ($crew_list as $item){
                foreach ($item['roomList'] as $roomItem){
                    if($roomItem['type'] == 'room'){
                        $roomNum = $roomNum + 1;
                    }else{
                        $groupNum = $groupNum + 1;
                    }
                }
            }
            $data['room_num'] = $roomNum;
            $data['group_num'] = $groupNum;
        }else{
            $data['crew_list'] = [];
            $data['room_num'] = 0;
            $data['group_num'] = 0;
        }

        if(!empty($data['role_list'])){
            $data['role_list'] = json_decode($data['role_list'],true);
        }else{
            $data['role_list'] = [];
        }

        $data['role_num'] = count($data['role_list']);

        $rst = $this->mapper->update($data['id'],$data);

        $this->mapper->clearCache($data['id']);
        return $rst;
    }

    public function rename(array $data): bool
    {
        $info = $this->mapper->findById($data['id']);
        if(empty($info)){
            throw new NormalStatusException("操作失败");
        }
        $rst = $this->mapper->update($data['id'],['name' => $data['name']]);
        $this->mapper->clearCache($data['id']);
        return $rst;
    }

    public function copy(array $params): bool
    {
        $info = $this->mapper->findById($params['id']);
        if(empty($info)){
            throw new NormalStatusException("操作失败");
        }
        $data = $info->toArray();
        unset($data['id'],$data['created_at'],$data['updated_at']);
        $data['name'] = $data['name'].' 复制';
        $id = $this->mapper->save($data);
        return $this->mapper->update($id,['sort' => $id]);
    }

    public function deleteScheme(array $params)
    {
        $info = $this->mapper->findById($params['id']);
        if(empty($info)){
            throw new NormalStatusException("操作失败");
        }

        $info->delete();
        $this->mapper->clearCache($params['id']);
        return true;
    }

    #[Transaction]
    public function changeSort(array $params)
    {
        $sourceId = $params['source_id'];
        $targetId = $params['target_id'];

        $sourceInfo = $this->mapper->findById($sourceId);

        $targetInfo = $this->mapper->findById($targetId);

        if(empty($sourceInfo) || empty($targetInfo)){
            throw new NormalStatusException("操作失败");
        }
        $this->mapper->update($sourceId,['sort' => $targetInfo->sort]);
        $this->mapper->update($targetId,['sort' => $sourceInfo->sort]);
        $this->mapper->clearCache($sourceId);
        $this->mapper->clearCache($targetId);
        return true;
    }

    public function getRoomAndRobotIds(mixed $id,array $roleIds): array
    {
        $info = $this->mapper->findById($id);
        if(empty($info)){
            return [];
        }

        if(empty($info->crew_list) || empty($info->role_list)){
            return [];
        }

        $crew_list = array_filter($info->crew_list,function ($item){
            return !empty($item['roomList']);
        });

        $list = [];
        foreach ($crew_list as $item){
            $roleList = array_filter($item['roleList'],function ($item) use ($roleIds){
                return in_array($item['id'],$roleIds) && !empty($item['robotIds']);
            });

            if(empty($roleList)){
                continue;
            }

            $robotIds = [];
            foreach ($roleList as $roleItem){
                $robotIds = array_merge($robotIds,$roleItem['robotIds']);
            }

            //获取在线的机器人ID
            $robotIds = ChRobot::query()
                ->whereIn('id',$robotIds)
                ->where('login_status',StatusConstants::ENABLE)
                ->pluck('id')
                ->toArray();
            if(empty($robotIds)){
                continue;
            }

            $roomList = $item['roomList'];
            $roomIdList = [];
            foreach ($roomList as $roomItem){
                if($roomItem['type'] == 'room'){
                    $roomIdList[] = $roomItem['value'];
                }else{
                    $roomIds = Db::table('ch_room_group_map')
                        ->where('group_id',$roomItem['value'])
                        ->pluck('room_id')
                        ->toArray();
                    if(!empty($roomIds)){
                        $roomIdList = array_merge($roomIdList,$roomIds);
                    }
                }
            }

            $roomRobotList = [];
            foreach ($roomIdList as $roomId){
                $roomRobotList[$roomId] = $robotIds;
            }
            $list = collect($list + $roomRobotList)->all();
        }
        return $list;
    }
}